package cn.qidd.keep.domain.web;

import cn.qidd.keep.domain.core.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@RestControllerAdvice
public class ControllerExceptionHandleAdvice {

    private final Logger logger = LoggerFactory.getLogger(ControllerExceptionHandleAdvice.class);

    @Autowired
    private MessageSource titleMessageSource;

    @ExceptionHandler(TokenException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ResponseEntity handler(WebRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("timestamp", System.currentTimeMillis());
        map.put("status", HttpStatus.UNAUTHORIZED);
        map.put("error", "Unauthorized");
        map.put("message", titleMessageSource.getMessage("title.unauthorized", null, "Unauthorized", Locale.SIMPLIFIED_CHINESE));
        map.put("path", request.toString());
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(map);
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity handler(MethodArgumentNotValidException e, WebRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("errors", e.getBindingResult().getAllErrors());
        map.put("timestamp", System.currentTimeMillis());
        map.put("status", HttpStatus.BAD_REQUEST.value());
        map.put("error", "Bad Request");
        map.put("message", titleMessageSource.getMessage(e.getMessage(), null, "Param Error", request.getLocale()));
        map.put("path", request.toString());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity handler(MissingServletRequestParameterException e, WebRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("errors", e.getMessage());
        map.put("timestamp", System.currentTimeMillis());
        map.put("status", HttpStatus.BAD_REQUEST.value());
        map.put("error", "Bad Request");
        map.put("message", titleMessageSource.getMessage("title.request.missing.parameters", new String[]{e.getParameterName(), e.getParameterType()}, "Param Error", request.getLocale()));
        map.put("path", request.toString());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(map);
    }

    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.OK)
    public Result handler(BusinessException e) {
        String message = null;
        try {
            message = titleMessageSource.getMessage(e.getMessage(), null, Locale.SIMPLIFIED_CHINESE);
        } catch (NoSuchMessageException e1) {
            return new Result<>(Result.Status.FAILURE, e.getMessage());
        }
        return new Result<>(Result.Status.FAILURE, message);
    }

    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity handler(Exception e, WebRequest request) {
        logger.error("请求【{}】出现错误...", request.getContextPath());
        logger.error(e.getMessage(), e);
        Map<String, Object> map = new HashMap<>();
        map.put("errors", e.getMessage());
        map.put("timestamp", System.currentTimeMillis());
        map.put("status", HttpStatus.INTERNAL_SERVER_ERROR);
        map.put("error", "Internal Server Error");
        map.put("message", titleMessageSource.getMessage("title.internal.server.error", null, "Internal Server Error", Locale.SIMPLIFIED_CHINESE));
        map.put("path", request.toString());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(map);
    }


}
